/**
 * @author liu_j@worksap.co.jp
 */
Ext.define('Goban.controller.GobanPanel', {
	extend: 'Ext.app.Controller',
	requires: ['Goban.data.Goban', 'Goban.util.Request'],
	views: ['GobanPanel'],
	refs: [{
		ref: 'gobanPanel',
		selector: 'gobanPanel'
	}],
	init: function() {
		this.control({
			'gobanPanel': {
				initGoban: this.onGobanInit,
				putGo: this.onPutGo
			}
		});
	},
	onGobanInit: function(panel) {
		var x = Goban.data.Goban.XNUM;
		var y = Goban.data.Goban.YNUM;
		var length = Goban.data.Goban.SQUAREWIDTH;
		var drawComponent = panel.down('draw#gobanDraw');
		var width = length * (x-1);
		var height = length * (y-1);
		var halfLength = length/2;
		panel.setSize(width + length + 2, height + length + 2);
		panel.setGoState(-1);
		panel.goban = [];
		panel.emptyNum = x * y;
		if(!panel.gameNum) {
			panel.gameNum = 1;
		} else {
			panel.gameNum++;
		}
		for(var i=0; i<x; i++) {
			panel.goban[i] = [];
			for(var j=0; j<y; j++) {
				panel.goban[i][j] = 0;
			}
		}
		drawComponent.surface.removeAll(true);
		var goban = drawComponent.surface.add({
		    type: 'rect',
		    x: 0,
		    y: 0,
		    width: width + length,
		    height: height + length,
		    fill: '#EAC100'
		});
		goban.show(true);
		goban.addListener('mousedown', this.onMouseDown);
		goban.panel = panel;
		for(var i=0; i<y; i++) {
			var line = drawComponent.surface.add({
			    type: 'rect',
			    x: halfLength,
			    y: halfLength+length*i,
			    width: width,
			    height: 1,
			    fill: '#000000'
			});
			line.show(true);
			line.addListener('mousedown', this.onMouseDown);
			line.panel = panel;
		}
		for(var i=0; i<x; i++) {
			var line = drawComponent.surface.add({
			    type: 'rect',
			    x: halfLength+length*i,
			    y: halfLength,
			    width: 1,
			    height: height,
			    fill: '#000000'
			});
			line.show(true);
			line.addListener('mousedown', this.onMouseDown);
			line.panel = panel;
		}
		if(x%2===1 && y%2===1) {
			var point = drawComponent.surface.add({
			    type: 'circle',
			    x: length*(x/2),
			    y: length*(y/2),
			    radius: length/10,
			    fill: '#000000'
			});
			point.show(true);
			point.addListener('mousedown', this.onMouseDown);
			point.panel = panel;
		}
	},
	onMouseDown: function(s, e, eOpts) {
		var panel = s.panel;
		var nextGoType = panel.getGoState();
		if(nextGoType === 0 || (nextGoType===-1 && Goban.data.Goban.BLACKPLAYER !== 0) ||
				(nextGoType===1 && Goban.data.Goban.WHITEPLAYER !== 0)) {
			return;
		}
		var pos = panel.getPosition();
		var x = e.getX() - pos[0];
		var y = e.getY() - pos[1];
		var goX = Math.floor(x / Goban.data.Goban.SQUAREWIDTH);
		var goY = Math.floor(y / Goban.data.Goban.SQUAREWIDTH);
		if(panel.goban[goX][goY]===0) {
			panel.fireEvent('putGo', panel, goX, goY);
		}
	},
	onPutGo: function(panel, x, y) {
		
		var width = Goban.data.Goban.SQUAREWIDTH;
		var halfWidth = Goban.data.Goban.SQUAREWIDTH / 2;
		var drawComponent = panel.down('draw#gobanDraw');
		var go = drawComponent.surface.add({
		    type: 'circle',
		    x: width*x+halfWidth,
		    y: width*y+halfWidth,
		    radius: halfWidth,
		    fill: '#000000'
		});
		var goState = panel.getGoState();
		var controlPanel = panel.up().down('controlPanel');
		controlPanel.fireEvent('countTime', controlPanel, goState);
		panel.goban[x][y] = goState;
		if(goState===-1) {
			panel.setGoState(1);
		} else {
			panel.setGoState(-1);
			go.setAttributes({fill: '#FFFFFF'}, true);
		}
		go.show(true);
		panel.emptyNum--;
		if(this.isWin(panel.goban, x, y)) {
			panel.setGoState(0);
			if(goState===-1) {
				Ext.MessageBox.show({
			        title: '勝利',
			        msg: '黒は勝ちました！',
			        width:300,
			        buttons: Ext.MessageBox.OK
				});
			} else {
				Ext.MessageBox.show({
			        title: '勝利',
			        msg: '白は勝ちました！',
			        width:300,
			        buttons: Ext.MessageBox.OK
				});
			}
		} else {
			if(panel.emptyNum<=0) {
				Ext.MessageBox.show({
			        title: '引き分け',
			        msg: '引き分けです！',
			        width:300,
			        buttons: Ext.MessageBox.OK
				});
				return;
			}
			var nextGoType = panel.getGoState();
			if((nextGoType===-1 && Goban.data.Goban.BLACKPLAYER !== 0) ||
					(nextGoType===1 && Goban.data.Goban.WHITEPLAYER !== 0)) {
				var aiLevel;
				var aiType;
				if(nextGoType===-1) {
					aiLevel = Goban.data.Goban.BLACKLEVEL;
					aiType = Goban.data.Goban.BLACKPLAYER;
				} else {
					aiLevel = Goban.data.Goban.WHITELEVEL;
					aiType = Goban.data.Goban.WHITEPLAYER;
				}
				var oldGameNum = panel.gameNum;
				Goban.util.Request.getNextMove(panel.goban, nextGoType, aiType, aiLevel, 
					function(response, eOpts) {
						var nextMove = Ext.decode(response.responseText);
						if(panel.gameNum === oldGameNum) {
							panel.fireEvent('putGo', panel, nextMove[0], nextMove[1]);
							controlPanel.fireEvent('record', controlPanel, nextGoType, nextMove[2], nextMove[3]);
						}
					}, function(response, eOpts) {
						Ext.MessageBox.show({
    						title: 'Error',
    						width: 450,
    						msg: response.responseText,
    						buttons: Ext.MessageBox.OK,
    						icon: Ext.MessageBox.WARNING
    					});
					}
				);
			}
		}
	},
	isWin: function(goban, x, y) {
		return (this.countSame(goban, x, y, 1, 0) + this.countSame(goban, x, y, -1, 0) -1)>=5 ||
				(this.countSame(goban, x, y, 0, 1) + this.countSame(goban, x, y, 0, -1) -1)>=5 ||
				(this.countSame(goban, x, y, 1, 1) + this.countSame(goban, x, y, -1, -1) -1)>=5 ||
				(this.countSame(goban, x, y, 1, -1) + this.countSame(goban, x, y, -1, 1) -1)>=5;	
	},
	countSame: function(goban, x, y, xOffset, yOffset) {
		var count = 0;
		var i = x;
		var j = y;
		var go = goban[x][y];
		while(i>=0 && i<goban.length && j>=0 && j<goban[i].length) {
			if(goban[i][j]===go) {
				count++;
				i += xOffset;
				j += yOffset;
			} else {
				break;
			}
		}
		return count;
	}
});